package com.ygp.dtp.core.thread;

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @description: 动态 ThreadPoolExecutors 中使用的默认 ThreadFactory。
 * @motto: 代码源于生活，高于生活艺术
 * @author: zhouhengzhe
 * @date: 2022/8/10 09:56
 * @since 1.0
 **/
@Slf4j
public class NamedThreadFactory implements ThreadFactory {


    private final ThreadGroup group;
    private final String namePrefix;

    /**
     * 是否开启守护线程
     */
    private final boolean daemon;

    /**
     * 线程优先级
     */
    private final Integer priority;

    /**
     * 线程名字下标
     */
    private final AtomicInteger seq = new AtomicInteger(1);

    /**
     * 未捕获的异常处理程序
     */
    private final Thread.UncaughtExceptionHandler uncaughtExceptionHandler;

    public NamedThreadFactory(String namePrefix, boolean daemon, Integer priority) {
        this.namePrefix = namePrefix;
        this.daemon = daemon;
        this.priority = priority;
        //系统安全管理
        SecurityManager s = System.getSecurityManager();
        //系统线程组/当前线程的线程组
        group = (s != null) ? s.getThreadGroup() : Thread.currentThread().getThreadGroup();
        this.uncaughtExceptionHandler = new DtpUncaughtExceptionHandler();
    }

    public NamedThreadFactory(String namePrefix) {
        this(namePrefix, false, Thread.NORM_PRIORITY);
    }

    public NamedThreadFactory(String namePrefix, boolean daemon) {
        this(namePrefix, daemon, Thread.NORM_PRIORITY);
    }

    /**
     * 构造一个新的 {@code Thread}。实现还可以初始化优先级、名称、守护进程状态、{@code ThreadGroup} 等。
     *
     * @param r 由新线程实例执行的可运行对象
     * @return 构造线程，如果创建线程的请求被拒绝，则返回 {@code null}
     */
    @Override
    public Thread newThread(Runnable r) {
        Thread thread = new Thread(group, r , namePrefix + "-thread-" + seq.getAndIncrement(), 0);
        thread.setDaemon(daemon);
        thread.setPriority(priority);
        thread.setUncaughtExceptionHandler(uncaughtExceptionHandler);
        return thread;
    }

    public static class DtpUncaughtExceptionHandler implements Thread.UncaughtExceptionHandler {
        @Override
        public void uncaughtException(Thread t, Throwable e) {
            log.error("线程： {} 抛异常：", t, e);
        }
    }
}
